module IP8088(clk,reset,ad,a,as,rd,wr,iom,ale,dtr,den,ready,test,intr,inta,nmi,hold,hlda,ss0,mnmx,t_ad,addr2);
	input clk,reset;	//clock and reset signal,clk rising edge enable,reset high enable
	inout [7:0] ad;		//external ad pins, 8 bits, address[7:0], data[7:0]
	output [15:8] a;	//external a pins, 8 bits, address[15:8]
	output [6:3] as;	//external as pins, 4 bits, address[19:16], state[6:3]
	output rd;		//rd pin, low enable
	output wr;		//wr pin, low enable
	output iom;		//iom pin, high means memory access, low means io access
	output ale;		//ale pin, high enable
	output dtr;		//dtr pin, low means read, high means write
	output den;		//den pin, low means data valid
	input ready;	//ready pin, high means data ready 
	input test;		//"wait for test" instruction, low enable 
	input intr;		//interrupt request, high enable 
	input inta;		//interrupt acknowledge, low enable
	input nmi;		//non-maskable interrupt, posedge enable							 
	input hold;		//indicate another master is requesting a local bus "hold", high enable
	output hlda;	//an acknowledge of hold request, high enable
	output ss0;		//status line
	input mnmx;		//MINIMUM/MAXIMUM, high indicate minimum, low indicate maxmum
	
	
	
	
	output [7:0]t_ad;
	output addr2;
	assign t_ad=ad;
	wire [16:0]addr;
	wire [11:0]addr2;
	assign addr2=addr[11:0];
	IP ipmodel(.clk(clk),.reset(reset),.ipinen(1'b0),.ipouten(1'b1),.ipinc(1'b1),.ipout(addr));
	SRAM sram_mod(.address(addr2),.clock(clk),.data(8'h00),.wren(1'b0),.q(ad)); 
	//IR ir_mod(.clk(clk),.reset(reset),.irhinen(),irlinen,irin,irout,euseladdr1,euoutaddr1,biuseladdr,biuoutaddr,euseladdr2,euoutaddr2,t_ir,t_irin,t_irhinen,t_irlinen);
endmodule

module IP(clk,reset,ipinen,ipin,ipouten,ipout,ipinc/*,t_ip*/); 
	input clk,reset;	//clock and reset signal,clk rising edge enable,reset high enable							 
	input ipinen;	//control bit of ip input
	input [15:0] ipin;	//data of ip input
						// ### linked with B-BUS ###
	input ipouten;		//control bit of ip output
	output [15:0] ipout;	//data of ip output
							// ### linke with B-BUS ###
	input ipinc;	//control bit of ip increment
//	output [15:0] t_ip;
//		assign t_ip = ipreg;	 
	
	reg [15:0] ipreg;
	
	assign ipout = (!reset&&ipouten)? ipreg: 16'bz;//change from bz to bx in 2009-1-28 14:18,and then change back to bx in 14:20
	
	always @(posedge clk) begin 
		if (reset) ipreg <= 0;		//start at 0x0000
		else begin 
			if (ipinen) ipreg <= ipin;
			if (ipinc) ipreg <= ipreg + 16'h0001;
		end
	end
	
endmodule



// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module SRAM (
	address,
	clock,
	data,
	wren,
	q);

	input	[11:0]  address;
	input	  clock;
	input	[7:0]  data;
	input	  wren;
	output	[7:0]  q;

	wire [7:0] sub_wire0;
	wire [7:0] q = sub_wire0[7:0];

	altsyncram	altsyncram_component (
				.wren_a (wren),
				.clock0 (clock),
				.address_a (address),
				.data_a (data),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.indata_aclr_a = "NONE",
		altsyncram_component.init_file = "SRAM.mif",
		altsyncram_component.intended_device_family = "Cyclone",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 4096,
		altsyncram_component.operation_mode = "SINGLE_PORT",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "UNREGISTERED",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.widthad_a = 12,
		altsyncram_component.width_a = 8,
		altsyncram_component.width_byteena_a = 1,
		altsyncram_component.wrcontrol_aclr_a = "NONE";


endmodule


`timescale 1 ns / 1 ps
module IR(clk,reset,irhinen,irlinen,irin,irout,euseladdr1,euoutaddr1,biuseladdr,biuoutaddr,euseladdr2,euoutaddr2,t_ir,t_irin,t_irhinen,t_irlinen); 
/*
	seladdr decoding:
		seladdr[2] indicates whether seladdr is valid
		seladdr[1]:  0 8bits     1 16bits
		seladdr[0]:  0 IR[2:0]    1 IR[5:3]
 */
	input clk,reset;	//clock and reset signal,clk rising edge enable,reset high enable
	input irhinen;		//control bit of data for ir high 8 bits
	input irlinen;		//control bit of data for ir low 8 bit
	input [7:0] irin;	//data for ir 8 bits
						//### linked with BCL ###
	output [15:0] irout;	//data from instruction register
							//### linked with uCONTROLLER ###
	input [2:0] euseladdr1;	//select which part of ir, seladdr[2] high means addrress valid
	output [3:0] euoutaddr1;	//EU_REG's address
							//### linked with EU_REG ###
	input biuseladdr;	//dedicate whether to select ir part, high enable
	output [1:0] biuoutaddr;	//BIU_REG's address
								// ### linked with BIU_REG ###
	
	input [2:0] euseladdr2;	//select which part of ir, seladdr[2] high means addrress valid
	output [3:0] euoutaddr2;	//EU_REG's address
							//### linked with EU_REG ###								
	
	//just for test
	output [15:0] t_ir;
		assign t_ir = irreg;
	output [7:0] t_irin;
		assign t_irin = irin;
	output t_irhinen;
		assign t_irhinen = irhinen;
	output t_irlinen;
		assign t_irlinen = irlinen;
								
	reg [15:0] irreg;
	
	assign irout = (!reset)? (t_irhinen)? {irin[7:0],irreg[7:0]}: (t_irlinen)? {irreg[15:8],irin[7:0]}: {irreg[15:0]}: 16'bz;
	
	assign euoutaddr1 = (reset)? 4'bz: (euseladdr1[1:0]==2'b01)? {euseladdr1[2],irreg[2:0]}:		//TR3 or TR4  or  SR3 or SR4
									(euseladdr1[1:0]==2'b10)? {euseladdr1[2],irreg[5:3]}:		//TR1 or TR2  or  SR1 or SR2
									(euseladdr1[1:0]==2'b11)? {euseladdr1[2],irreg[10:8]}: 4'bz; 	//TR5 or TR6  or  SR6 or SR6 
			
	assign biuoutaddr = (biuseladdr)? irreg[4:3]: irreg[12:11];
	
	assign euoutaddr2 = (reset)? 4'bz: (euseladdr2[1:0]==2'b01)? {euseladdr2[2],irreg[2:0]}:		//TR3 or TR4  or  SR3 or SR4
									(euseladdr2[1:0]==2'b10)? {euseladdr2[2],irreg[5:3]}:		//TR1 or TR2  or  SR1 or SR2
									(euseladdr2[1:0]==2'b11)? {euseladdr2[2],irreg[10:8]}: 4'bz; 	//TR5 or TR6  or  SR6 or SR6 
																								  
	always @(posedge clk) begin 
		if (reset) begin
			irreg[15:0] <= 0;
		end
		else begin
			if (irhinen) irreg[15:8] <= irin;		//irh refresh
			if (irlinen) irreg[7:0] <= irin; 		//irl refresh
		end
	end
	
endmodule






module CLK_DIV(clk,reset,tout);
input clk,reset;
output [11:0]tout;
reg [11:0]tout;
//assign tout=
always @ (posedge clk)
			begin
				tout[0] <= tout[11] || reset;
				tout[1] <= tout[0] && !reset;
				tout[2] <= tout[1] && !reset;
				tout[3] <= tout[2] && !reset;
				tout[4] <= tout[3] && !reset;
				tout[5] <= tout[4] && !reset;
				tout[6] <= tout[5] && !reset;
				tout[7] <= tout[6] && !reset;
				tout[8] <= tout[7] && !reset;
				tout[9] <= tout[8] && !reset;
				tout[10] <= tout[9] && !reset;
				tout[11] <= tout[10] && !reset;
			end
endmodule  

module CONTROL(clk,reset,irin,frin,cxzero,busokay,calokay,test,intr,nmi,mtype,optype);
/*
	uflag register:
		------------------------------------------
		|DSV |WORD|MODF|PREF|REPF|REPZF|LOCKF|NMIF|
		------------------------------------------
 */
	input uclk,reset;	//uclock and reset signal,clk rising edge enable,reset high enable 							   
	input [15:0] irin;		//instruction
							// ### linked with IR ###
	input [15:0] frin;		//uflag
							// ### linked with ALU ###
	input cxzero;		//indicates whether cx is zero
	input busokay;		//indicates whether bus access overs
	input calokay;		//indicates whether alu calculation overs 
	input test;		//"wait for test" instruction, low enable 
	input intr;		//interrupt request, high enable 
	input nmi;		//non-maskable interrupt
	output lockf;	 //LOCK tag
	output pref;	 //PREFIX tag
	output [3:0]mtype;  //control bits for bcl mtype
	output [5:0]optype; //control bits for alu calculate type
	
	wire dbir = (irin == 16'h01) || (irin == 16'h02);//to dectect whether the ir is 1 byte 
	
	reg [2:0]eu_state;
	always @(posedge clk)
	begin
		if(reset)
			begin
				eu_state <= 3'b000;
			end
		else
			begin//output 
				casex(eu_reg)
				3'b000:begin//fetch the first byte of instruction
						if(busokay)
							begin 
							 eu_state <= 3'b001;
							 irlin <= 1'b1;
							 ipinc <= 1'b1;
							end
						 else
						    begin
					         
					         mtype <= 4'b1000;//1st bit to control whether to    
					        end
					   end
				3'b001:begin//fetch the second byte of instruction
			                if(dbir)//if the ir just 1 byte
			                   begin
			                     eu_state <= 3'b010;
			                   end
			                 else 
								begin
									if(busokay)
										begin 
										 eu_state <= 3'b001;
										 irhin <= 1'b1;
										 ipinc <= 1'b1;
										end
									 else
										begin
										 mtype <= 4'b1000;//1st bit to control whether to    
										end
								end
			           end
			    3'b010:begin//fetch data
			             casex(irin[15:10])
			                  6'b100010://mov type instructions
								begin
									casex(ir[9:8])//D=ir[9],W=ir[8],
								     //D=0:from reg;D=1:into reg;
								     //W=0:trans byte;W=1:trans word
									  2'b00:
										begin
											
										end
									  2'b01:
									    begin
											if(busokay)
													begin 
													 eu_state <= 3'b011;
													end
												 else
													begin
													 mtype <= 4'b1001;//load mem to reg
													    
													end 
								        end
									  2'b10:
									  2'b11:
								end
			           end
			    3'b011:begin//execute state
			             casex(irin)
			           end
			    3'b100:begin//write data
			             casex(irin)
			           end
			
			end
	end

endmodule

`timescale 1 ns / 1 ps
module BCL(clk,reset,mtype,addrin,ad,a,as,datain,re,we,iom,datatoir,ale,dtr,den,ready,busokay,inta,hold,hlda,ss0,selseg,iflag,mnmx,lockf,numokay,t_buscycle);
/*
	control how to interact with memory or io system
 */
	input clk,reset;	//clock and reset signal,clk rising edge enable,reset high enable
	input [3:0] mtype;	//control how to do
	input [19:0] addrin;	//input address,will send to external address bus
	inout [7:0] ad;		//address data multi-wires, address[7:0], data[7:0]
						//### linked with ad ###
	output [15:8] a;	//address wires only, address[15:8]
						//### linked with a ###
	output [6:3] as;	//address state multi-wires,address[19:16] 
						//### linked with as ###
	inout [15:0] datain;	//data to interact with internal data bus
							// ### linked with B_BUS ###
	output re;		//control bit of read signal
					//### linked with re ###
	output we;		//control bit of write signal
					//### linked with we ###
	output iom;		//control bit of io access or memory access
					//### linked with iom ###
	output [7:0] datatoir; 	//instruction data for instruction registers
							//### linked with IR ###
	output ale;		//control bit of address output signal
					//### linked with ale ###
	output dtr;		//control bit of data direction
					//### linked with dtr ###
	output den;	 	//control bit of data signals
					//### linked with den ###
	input ready;	
					//### linked with ready ###
	output busokay;		//determines whether bus operation completeed
						//### linked with uCONTROLLER ###
	output inta;	//interrupt acknowledge
	input hold;		//indicate another master is requesting a local bus "hold", high enable
	output hlda; 	//an acknowledge of hold request, high enable
	output ss0;		//status line
	input [1:0] selseg;	//indicate which segment register is using
	input iflag;	//interrupt enable flag	
	input mnmx;		//MINIMUM/MAXIMUM, high indicate minimum, low indicate maxmum
	input lockf;	//LOCK tag
	output numokay;
	
	output [2:0] t_buscycle;
		assign t_buscycle = buscycle;
						
	reg [7:0] ebbuf;	//temporary register to keep one byte
	reg [2:0] buscycle;		//two bits' state to cooperate with external bus
	reg [7:0] ad;	//as
	reg [15:8] a;	//a
	reg [6:3] as;	//as
	reg ale;	//ale
	reg re;		//re
	reg wereg;		//we
	reg iom;		//iom
	reg dtr;		//dtr
	reg den;		//den
	reg [7:0] datatoir;	//datatoir
	reg [15:0] datainreg;	//datain
	reg inta;	//inta
	reg hlda;	//hlda
	reg ss0;		//ss0
	
//	assign ad = ad;
//	assign a = a;
//	assign as = as;
//	assign ale = ale;
//	assign re = re;
	assign we = ((!reset)&&(!mnmx))? (lockf)? 1'b0: 1'b1: wereg;
//	assign iom = iom;
//	assign dtr = dtr;
//	assign den = den;
//	assign datatoir = datatoir;
	assign datain = ((mtype[3]&&mtype[2])||(mtype==4'b0011))? datainreg : 16'bz;
//	assign inta = inta;
//	assign hlda = hlda;
//	assign ss0 = ss0;
		
	assign busokay = (!reset)? (buscycle==3'b000)? 1'b1: 1'b0: 1'b0;
	assign numokay = (!reset)? ((buscycle==3'b000)||(buscycle==3'b100))? 1'b1: 1'b0: 1'b0;
	
	always @(negedge clk) begin 
		if (reset) begin 
			ebbuf <= 0;  buscycle <= 3'b000;
			ad <= 8'bz;  a <= 8'bz;
			as <= 4'bz;	ale <= 1'b0;
			re <= 1'b1;  wereg <= 1'b1;
			iom <= 1'b0;  dtr <= 1'b0;
			den <= 1'b1;  datatoir <= 8'bz;
			datainreg <= 16'bz;  inta <= 1'b1;
			hlda <= 1'b0;  ss0 <= 1'b1;
		end
		else begin
			casex (buscycle)
				3'b000: 	begin
						if (mnmx&&hold) begin 
							hlda <= 1'b1;
							ad <= 8'bz;  a <= 8'bz;	as <= 4'bz;//change in 2009-1-28 11:55 from as <= 8'bz to as <= 4'bz;
							ale <= 1'b0;	re <= 1'bz;  wereg <= 1'bz;
							iom <= 1'bz;	dtr <= 1'bz;	den <= 1'bz;
							inta <= 1'b1;datainreg <= 16'bz; ss0 <= 1'b1;
							buscycle <= 3'b001;
						end
						else if ((mtype[3]||mtype[2])||(mtype[1]&&mtype[0])) begin	   //T1
							casex (mtype)
								4'b0011: begin		//intr
											iom <= (mnmx)? 1'b1: 1'b0;
										 	dtr <= 1'b0;
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//interrupt acknowledge
										 end
								4'b0100: begin		// read memory to irh
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
							   				{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//code access
										 end
								4'b0101: begin		// read memory to irl
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
							   				{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//code access
										 end   						
								4'b0110: begin 		//read memory access
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
							   				{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read memory
										 end
								4'b0111: begin		//read io access
											iom <= (mnmx)? 1'b0: 1'b1;		//iom low enables io access
							   				{as,a,ad} <= {4'b0,addrin[15:0]};	//io address, 16 bits, high 4 bits zero
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read io port
										end
								4'b1000: begin		//write memory access
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
							   				{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b1;		//dtr high means write memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//write memory
										 end							
								4'b1001: begin		//write memory access
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
							   				{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b1;		//dtr high means write memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//write memory
										 end
								4'b1010: begin		//write io access
											iom <= (mnmx)? 1'b0: 1'b1;		//iom low enables io access
							   				{as,a,ad} <= {4'b0,addrin[15:0]};	//io address, 16 bits, high 4 bits zero
											dtr <= 1'b1;		//dtr high means write memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//write io
										 end
								4'b1011: begin		//write io access
											iom <= (mnmx)? 1'b0: 1'b1;		//iom low enables io access
							   				{as,a,ad} <= {4'b0,addrin[15:0]};	//io address, 16 bits, high 4 bits zero
											dtr <= 1'b1;		//dtr high means write memory
											ss0 <= (!mnmx)? 1'b1: 1'b0;		//write io
										 end
								4'b1100: begin		//read memory access
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
											{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read memory
										 end
								4'b1110: begin		//read memory access
											iom <= (mnmx)? 1'b1: 1'b0;		//iom high enables memory access
											{as,a,ad} <= addrin;	//memory address, 20 bits
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read memory
										 end
								4'b1101: begin		//read io access
											iom <= (mnmx)? 1'b0: 1'b1;		//iom low enables io access
							   				{as,a,ad} <= {4'b0,addrin[15:0]};	//io address, 16 bits, high 4 bits zero
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read io port
										 end
								4'b1111: begin		//read io access
											iom <= (mnmx)? 1'b0: 1'b1;		//iom low enables io access
							   				{as,a,ad} <= {4'b0,addrin[15:0]};	//io address, 16 bits, high 4 bits zero
											dtr <= 1'b0;		//dtr low means read memory
											ss0 <= (!mnmx)? 1'b1: 1'b1;		//read io port
										 end
							endcase
							ale <= 1'b1;		//ale high enables memory or io system to lock address
							buscycle <= 3'b001;	//next bus cycle
						end
						else begin
								ad <= 8'bz;  a <= 8'bz;
								as <= 4'bz;	ale <= 1'b0;
								re <= 1'b1;  wereg <= 1'b1;
								//iom <= 1'b0;  
								dtr <= 1'b0;
								den <= 1'b1;  datatoir <= 8'bz;
								datainreg <= 16'bz;  ss0 <= 1'b1;		
								inta <= 1'b1; 	//all reset
						end
						end
				3'b001: begin 
						if (hlda) begin
							if (!hold) begin
								hlda <= 1'b0;
								buscycle <= 3'b000;
							end			  
						end
						else if ((mtype[3]||mtype[2])||(mtype[1]&&mtype[0])) begin		 //T2
							ad <= 8'bz;		//ad set to Z
							ale <= 1'b0;		//ale low means address invalid	
							den <= 1'b0;	 	//den low means data valid
							buscycle <= 3'b010; 	//next cycle
							casex (mtype)
								4'b0011:	//intr
										begin
										 as[6:3] <= 4'bz;
										 inta <= 1'b0;	//interrupt ackownledge enable
										 re <= 1'b1;
										 wereg <= 1'b1;
										end
								4'b0100: 	//read memory to irh
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= 2'b10;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b0101: 	//read memory to irl 
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= 2'b10;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b0110: 	//read memory to ebbuf 
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= selseg;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b0111: 	//read io to ebbuf
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= 2'b10;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b1000: begin		//write b-bus low to memory
											as[6] <= 1'b0;
										 	as[5] <= iflag;
											as[4:3] <= selseg;
											ad <= datain[7:0]; 	// low 8 bit data to write
											re <= 1'b1;
											wereg <= 1'b0;	//we low  enable write access
										 end
								4'b1001: begin 		//write b-bus high to memory
											as[6] <= 1'b0;
										 	as[5] <= iflag;
											as[4:3] <= selseg;
											ad <= datain[15:8];	//high 8 bit data to write
											re <= 1'b1;
											wereg <= 1'b0;	//we low enable write access
										 end
								4'b1010: begin		//write b-bus low to io	
											as[6] <= 1'b0;
										 	as[5] <= iflag;
											as[4:3] <= 2'b10;
											ad <= datain[7:0]; 	// low 8 bit data to write
											re <= 1'b1;
											wereg <= 1'b0;	//we low  enable write access
										 end
								4'b1011: begin 		//write b-bus high to io 
											as[6] <= 1'b0;
										 	as[5] <= iflag;
											as[4:3] <= 2'b10;
											ad <= datain[15:8];	//high 8 bit data to write
											re <= 1'b1;
											wereg <= 1'b0;	//we low enable write access
										 end
								4'b1100: 	//read memory to b-bus low
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= selseg;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b1101: 	//read io to b-bus low
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= selseg;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b1110: 	//read memory to b-bus high, ebbuf to b-bus low
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= selseg;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
								4'b1111: 	//read memory to b-bus high, ebbuf to b-bus low
										begin
										 as[6] <= 1'b0;
										 as[5] <= iflag;
										 as[4:3] <= selseg;
										 re <= 1'b0;		//re low enable read access
										 wereg <= 1'b1;
										end
							endcase
						 end
						end
				3'b010: if (mtype[3]|mtype[2]) begin	 	//T3
						if (ready) buscycle <= 3'b011;		//wait for external ready signal, high enable
											//else state remain initial T3
					   end
					   else if (mtype==4'b0011) begin
						buscycle <= 3'b011;						    
					   end
				3'b011: if ((mtype[3]||mtype[2])||(mtype[1]&&mtype[0])) begin		//T4
							ad <= 8'bz;  a <= 8'bz;
							as <= 4'bz;	ale <= 1'b0;
							//re <= 1'b0;  wereg <= 1'b1;
							//iom <= 1'b0;  
							//dtr <= 1'b0;
							den <= 1'b1;  datatoir <= 8'bz;
							datainreg <= 16'bz;  ss0 <= 1'b1;		
							inta <= 1'b1; 	//all reset
							casex (mtype)
								4'b0011: begin		//intr
											datainreg <= {8'b0,ad};										 	
										 end
								4'b010x: begin		//mem => ir
											datatoir <= ad;
										 end
								4'b011x: begin		//mem/io => ebbuf
											ebbuf <= ad;
										 end
								4'b10xx: begin		//write mem/io
											ad <= 8'bz;
										end
								4'b1100: begin		//mem => b-bus[7:0],sign extended
											datainreg <= {ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad};
										 end		
								4'b1110: begin		//{mem,ebbuf} => b-bus[15:0]
											datainreg <= {ad,ebbuf};
										end
								4'b1101: begin		//io => b-bus[7:0],sign extended
											datainreg <= {ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad[7],ad};
										 end 
								4'b1111: begin		//{io,ebbuf} => b-bus[15:0]
											datainreg <= {ad,ebbuf};
										 end
							endcase	
							buscycle <= 3'b100;	//reset bus cycle
						end
				3'b100: begin
						buscycle <=3'b000;
						/*ad <= 8'bz;  a <= 8'bz;
						as <= 4'bz;	ale <= 1'b0;
						re <= 1'b1;  wereg <= 1'b1;
						//iom <= 1'b0;
						dtr <= 1'b0;
						den <= 1'b1;  datatoir <= 8'bz;
						datainreg <= 16'bz;  ss0 <= 1'b1;		
						inta <= 1'b1; 	//all reset
						buscycle <= 3'b000;*/
					end			
			endcase		
		end
	end
		
endmodule



`timescale 1 ns / 1 ps
module BIU_REG(clk,reset,addrr1,re1,datar1,addrr2,re2,datar2,addrw,we,dataw,ptagin,ptagen,selseg,pref); 
/* 
	--------------------------
	|           ES			  |
	--------------------------
	|           CS			  |
	--------------------------
	|           SS			  |	
	--------------------------
	|           DS			  |
	--------------------------
	decode: 00 ES  01 CS  10 SS  11 DS
	two read port,one write port
 */
	input clk,reset;	//clock and reset signal,clk rising edge enable,reset high enable
	input [1:0] addrr1;		//address of read port 1
	input re1;		//control bit of read port 1, high enable
	output [15:0] datar1;	//data of read port 1
							//### linked with MAR_ADDER ###
	input [1:0] addrr2;		//address of read port 2
	input re2;		//control bit of read port 2, high enable
	output [15:0] datar2;	//data of read port 2
							//### linked with B_BUS ###
	input [1:0] addrw;		//address of write port				 	
	input we;		//control bit of write port, high enable
	input [15:0] dataw;		//data of write port
							//### linked with B_BUS ###
	input [1:0] ptagin;		//addrress of prefix segment
	input ptagen;		//control bit of prefix segment, high enable 
	output [1:0] selseg;		//indicate which segment register is using
								//linked with BCL
	input pref;		//PREFIX tag, indicate whether ptag should be valid, high enable
	
	reg [15:0] biu_reg[3:0];	//ES:biu_reg[0] CS:biu_reg[1] SS:biu_reg[2] DS:biu_reg[3]  
	reg [1:0] ptag;		//ptag indicate the prefix address
	reg [1:0] selsegreg;	//selseg
//	reg [15:0] datar1reg;	//datar1
//	reg [15:0] datar2reg;	//datar2
						
	//assign datar1 = ((!reset)&&(re1))? (pref&&(addrr1[1]&&addrr1[0]))? biu_reg[ptag]: biu_reg[addrr1]: 16'bz; 
		//from this, we suggest read port 1 should link with MAR
	assign datar1 = ((!reset)&&(re1))?  (pref&&(addrr1[1]&&addrr1[0]))? 
						(ptag==2'b00)? biu_reg[0]:
						(ptag==2'b01)? biu_reg[1]:
						(ptag==2'b10)? biu_reg[2]:
						(ptag==2'b11)? biu_reg[3]: 16'bz:
						(addrr1==2'b00)? biu_reg[0]:
						(addrr1==2'b01)? biu_reg[1]:
						(addrr1==2'b10)? biu_reg[2]:
						(addrr1==2'b11)? biu_reg[3]: 16'bz: 16'bz;
	assign datar2 = ((!reset)&&(re2))? (addrr2==2'b00)? biu_reg[0]:
					   (addrr2==2'b01)? biu_reg[1]:
					   (addrr2==2'b10)? biu_reg[2]:
					   (addrr2==2'b11)? biu_reg[3]: 16'bz: 16'bz;
		//read port 2 should link with B_BUS
	assign selseg = selsegreg;		
	
	always @(posedge clk) begin
		if (reset) begin
			biu_reg[0] <= 0;	biu_reg[1] <= 0;
			biu_reg[2] <= 0;	biu_reg[3] <= 0;	//segment registers assign to 0
			ptag <= 0;	//prefix address should be invalid
			selsegreg <= 2'b10;		//code or none
		end
		else begin
/*			if (re1) begin
				if (pref&&(addrr1[1]&&addrr1[0])) begin //prefix segment
					case (ptag)
						2'b00: datar1reg <= biu_reg[0];
						2'b01: datar1reg <= biu_reg[1];
						2'b10: datar1reg <= biu_reg[2];
						2'b11: datar1reg <= biu_reg[3];
					endcase
				end
				else begin		//normal
					case (addrr1)
						2'b00: datar1reg <= biu_reg[0];
						2'b01: datar1reg <= biu_reg[1];
						2'b10: datar1reg <= biu_reg[2];
						2'b11: datar1reg <= biu_reg[3];
					endcase
				end
			end
			if (re2) begin
				case (addrr2)
					2'b00: datar2reg <= biu_reg[0];
					2'b01: datar2reg <= biu_reg[1];
					2'b10: datar2reg <= biu_reg[2];
					2'b11: datar2reg <= biu_reg[3];
				endcase
			end 		*/
			if (we) begin	//we enable, write segment register	
				case (addrw)
					2'b00: biu_reg[0] <= dataw;
					2'b01: biu_reg[1] <= dataw;
					2'b10: biu_reg[2] <= dataw;
					2'b11: biu_reg[3] <= dataw;
				endcase
			end
			if (re1) begin
				selsegreg <= (pref)? ptag: addrr1;
			end
			if (ptagen) begin
				ptag <= ptagin;		//write prifix segment
			end
		end
	end
	
endmodule

`timescale 1 ns / 1 ps
module EU_REG(clk,reset,re,addrr,datar,we,addrw,dataw,cxzero);
/*
	encoding: 0000 AL   0001 CL   0010 DL   0011 BL
			  0100 AH   0101 CH   0110 DH   0111 BH
			  1000 AX   1001 CX   1010 DX   1011 BX
			  1100 SP   1101 BP   1110 SI   1111 DI
 */
	input clk,reset; 	//clock and reset signal,clk rising edge enable,reset high enable
	input re;	//control bit of read port
	input [3:0] addrr;	//address of read port
						//### linked with uCONTROLLER or IR ###
	output [15:0] datar;	//data of read port
							// ### linked with B-BUS
	input we;	//control bit of write port
	input [3:0] addrw; 		//address of write port
							// ### linked with uCONTROLLER or IR ###
	input [15:0] dataw;		//data of write port
							// ### linked with B-BUS ###
	output cxzero;			//indicate whether cx is zero
	
	reg [7:0] eureg[15:0];
//	reg [15:0] datartemp;
	reg [7:0] datah;	 
							
	//assign datar = (reset||(!re))? 16'bz: (addrr[3])? datartemp[15:0]: {datartemp[7],datartemp[7],datartemp[7],datartemp[7],datartemp[7],datartemp[7],datartemp[7],datartemp[7],datartemp[7:0]};
	assign datar = (reset||(!re))? 16'bz: 	(addrr==4'b0000)? {datah[0],datah[0],datah[0],datah[0],datah[0],datah[0],datah[0],datah[0],eureg[0]}:
						(addrr==4'b0001)? {datah[1],datah[1],datah[1],datah[1],datah[1],datah[1],datah[1],datah[1],eureg[1]}:
						(addrr==4'b0010)? {datah[2],datah[2],datah[2],datah[2],datah[2],datah[2],datah[2],datah[2],eureg[2]}:
						(addrr==4'b0011)? {datah[3],datah[3],datah[3],datah[3],datah[3],datah[3],datah[3],datah[3],eureg[3]}:
						(addrr==4'b0100)? {datah[4],datah[4],datah[4],datah[4],datah[4],datah[4],datah[4],datah[4],eureg[4]}:
						(addrr==4'b0101)? {datah[5],datah[5],datah[5],datah[5],datah[5],datah[5],datah[5],datah[5],eureg[5]}:
						(addrr==4'b0110)? {datah[6],datah[6],datah[6],datah[6],datah[6],datah[6],datah[6],datah[6],eureg[6]}:
						(addrr==4'b0111)? {datah[7],datah[7],datah[7],datah[7],datah[7],datah[7],datah[7],datah[7],eureg[7]}:
						(addrr==4'b1000)? {eureg[4],eureg[0]}:
						(addrr==4'b1001)? {eureg[5],eureg[1]}:
						(addrr==4'b1010)? {eureg[6],eureg[2]}:
						(addrr==4'b1011)? {eureg[7],eureg[3]}:
						(addrr==4'b1100)? {eureg[12],eureg[8]}:
						(addrr==4'b1101)? {eureg[13],eureg[9]}:
						(addrr==4'b1110)? {eureg[14],eureg[10]}:
						(addrr==4'b1111)? {eureg[15],eureg[11]}: 16'bz;
	
	assign cxzero = (!reset&&({eureg[5],eureg[1]}==0))? 1'b1: 1'b0;

	always @(posedge clk) begin 
		if (reset) begin
			eureg[0] <= 8'b0;	eureg[1] <= 8'b0;	eureg[2] <= 8'b0;	eureg[3] <= 8'b0;
			eureg[4] <= 8'b0;	eureg[5] <= 8'b0;	eureg[6] <= 8'b0;	eureg[7] <= 8'b0;
			eureg[8] <= 8'b0;	eureg[9] <= 8'b0;	eureg[10] <= 8'b0;	eureg[11] <= 8'b0;
			eureg[12] <= 8'b0;	eureg[13] <= 8'b0;	eureg[14] <= 8'b0;	eureg[15] <= 8'b0;
			datah <= 8'b0;
		end
		else begin
			/*if (re) begin
				case (addrr)
					4'b0000: datartemp <= {8'bz,eureg[0]};
					4'b0001: datartemp <= {8'bz,eureg[1]};
					4'b0010: datartemp <= {8'bz,eureg[2]};
					4'b0011: datartemp <= {8'bz,eureg[3]};
					4'b0100: datartemp <= {8'bz,eureg[4]};
					4'b0101: datartemp <= {8'bz,eureg[5]};
					4'b0110: datartemp <= {8'bz,eureg[6]};
					4'b0111: datartemp <= {8'bz,eureg[7]};
					4'b1000: datartemp <= {eureg[4],eureg[0]};
					4'b1001: datartemp <= {eureg[5],eureg[1]};
					4'b1010: datartemp <= {eureg[6],eureg[2]};
					4'b1011: datartemp <= {eureg[7],eureg[3]};
					4'b1100: datartemp <= {eureg[12],eureg[8]};
					4'b1101: datartemp <= {eureg[13],eureg[9]};
					4'b1110: datartemp <= {eureg[14],eureg[10]};
					4'b1111: datartemp <= {eureg[15],eureg[11]};
				endcase
			end */
			if (we) begin
				case (addrw)
					4'b0000: begin 
						eureg[0] <= dataw[7:0];
						datah[0] <= dataw[7];
					end
					4'b0001: begin
						eureg[1] <= dataw[7:0];
						datah[1] <= dataw[7];
					end
					4'b0010: begin
						eureg[2] <= dataw[7:0];
						datah[2] <= dataw[7];
					end
					4'b0011: begin
						eureg[3] <= dataw[7:0];
						datah[3] <= dataw[7];
					end
					4'b0100: begin
						eureg[4] <= dataw[7:0];
						datah[4] <= dataw[7];
					end
					4'b0101: begin
						eureg[5] <= dataw[7:0];
						datah[5] <= dataw[7];
					end
					4'b0110: begin
						eureg[6] <= dataw[7:0];
						datah[6] <= dataw[7];	
					end
					4'b0111: begin
						eureg[7] <= dataw[7:0];
						datah[7] <= dataw[7];
					end
					4'b1000: {eureg[4],eureg[0]} <= dataw;
					4'b1001: {eureg[5],eureg[1]} <= dataw;
					4'b1010: {eureg[6],eureg[2]} <= dataw;
					4'b1011: {eureg[7],eureg[3]} <= dataw;
					4'b1100: {eureg[12],eureg[8]} <= dataw;
					4'b1101: {eureg[13],eureg[9]} <= dataw;
					4'b1110: {eureg[14],eureg[10]} <= dataw;
					4'b1111: {eureg[15],eureg[11]} <= dataw;
				endcase 
			end				
		end
	end
	
endmodule 